﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Gmantis.Controls;

namespace Gmantis.Imaging
{
    [TemplatePart(Name = "Image", Type = typeof(Image))]
    public class Image : Control
    {
        // Fields
        internal Image _elementImage;
        internal const string ImageElementName = "Image";
        public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(Image), new PropertyMetadata(new PropertyChangedCallback(Image.OnSourcePropertyChanged)));
        public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(Image), new PropertyMetadata(Stretch.Uniform));

        // Methods
        public Image()
        {
            base.DefaultStyleKey = typeof(Image);
            this.SetCustomDefaultValues();
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void OnAfterApplyTemplate()
        {
            this.OnSourceChanged(null);
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._elementImage = this.GetTemplateChild<Image>("Image", true, ref errors);
            if (!string.IsNullOrEmpty(errors))
            {
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to Image.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.OnAfterApplyTemplate();
            }
        }

        private void OnSourceChanged(ImageSource oldValue)
        {
            if (this._elementImage != null)
            {
                this._elementImage.Source = this.Source;
            }
        }

        private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Image image = d as Image;
            ImageSource oldValue = (ImageSource)e.OldValue;
            image.OnSourceChanged(oldValue);
        }

        private void SetCustomDefaultValues()
        {
        }

        // Properties
        [TypeConverter(typeof(ImageSourceConverter))]
        public ImageSource Source
        {
            get
            {
                return (ImageSource)base.GetValue(SourceProperty);
            }
            set
            {
                base.SetValue(SourceProperty, value);
            }
        }

        public Stretch Stretch
        {
            get
            {
                return (Stretch)base.GetValue(StretchProperty);
            }
            set
            {
                base.SetValue(StretchProperty, value);
            }
        }
    }
}
